#include "VolumeJsonWriter.h"
#include "VolumeGridData.h"
#include "OCMain/zip/gzstream.h"
#include "OCMain/Timer.h"
#include "json/json.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"

namespace OCPP
{
	namespace Volume
	{
		VolumeJsonWriter::VolumeJsonWriter()
		{
			_typeExtension = "json";
		}

		bool VolumeJsonWriter::write(GridData& gridData, const VolumeOptions& options)
		{
			std::unique_ptr<std::ostream> outStream = getOutStream(gridData, options, false);
			gridData.read(options);

			const auto& extent = gridData.extent;

			rapidjson::StringBuffer buffer;
			rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
			writer.StartObject();
			writer.Key("numLon");
			writer.Int(extent.dimX);
			writer.Key("numLat");
			writer.Int(extent.dimY);
			writer.SetMaxDecimalPlaces(6);
			writer.Key("startLon");
			writer.Double(extent.rectangle.west);
			writer.Key("endLon");
			writer.Double(extent.rectangle.east);
			writer.Key("startLat");
			writer.Double(extent.rectangle.south);
			writer.Key("endLat");
			writer.Double(extent.rectangle.north);

			if (extent.dimZ > 1)
			{
				writer.Key("numLevel");
				writer.Int(extent.dimZ);
				writer.SetMaxDecimalPlaces(1);
				writer.Key("levelData");
				writer.StartArray();
				for (const auto& value : gridData.levelData)
				{
					writer.Double(value);
				}
				writer.EndArray();
			}

			writer.Key("DS");
			writer.SetMaxDecimalPlaces(3);

			writer.StartArray();
			const auto& vecFloat = gridData.gridDataValue->_vecFloat;
			auto size = vecFloat.size();
			for (auto i = 0; i < size; i++)
			{
				float value = vecFloat[i];
				writer.Double(value);
			}
			writer.EndArray();

			writer.EndObject();

			*outStream << buffer.GetString();

			onWriteDone(*outStream);

			return VolumeWriter::write(gridData, options);
		}

		bool VolumeJsonWriter::write(const VolumeGridData& ncGridData, const VolumeOptions& options)
		{
			std::unique_ptr<std::ostream> outStream = getOutStream(ncGridData, options);

			if (outStream == nullptr)
			{
				return false;
			}
			const auto& extent = ncGridData.getExtent();
			size_t size = ncGridData.getSize();

			rapidjson::StringBuffer buffer;
			rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
			writer.StartObject();
			writer.Key("numLon");
			writer.Int(extent.dimX);
			writer.Key("numLat");
			writer.Int(extent.dimY);

			writer.SetMaxDecimalPlaces(6);
			writer.Key("startLon");
			writer.Double(extent.xMin);
			writer.Key("endLon");
			writer.Double(extent.xMax);
			writer.Key("startLat");
			writer.Double(extent.yMin);
			writer.Key("endLat");
			writer.Double(extent.yMax);

			if (extent.dimZ > 1)
			{
				writer.Key("numLevel");
				writer.Int(extent.dimZ);
			}

			writer.Key("DS");
			writer.SetMaxDecimalPlaces(3);
			writer.StartArray();
			for (size_t i = 0; i < size; i++)
			{
				float value = ncGridData.getFloat(i);
				if (!ncGridData.isValidValue(value))
				{
					if (ncGridData._fillValue.has_value())
					{
						value = ncGridData._fillValue.value();
					}
					else
					{
						value = getFillValue();
					}
				}
				writer.Double(value);
			}
			writer.EndArray();
			writer.EndObject();

			*outStream << buffer.GetString();

			onWriteDone(*outStream);

			return VolumeWriter::write(ncGridData, options);
		}
	}
}


